home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume2 / duonly < prev    next >
Encoding:
Internet Message Format  |  1991-08-07  |  21.5 KB

  1. From: dennis@rlgvax.UUCP (Dennis.Bednar)
  2. Newsgroups: comp.sources.misc
  3. Subject: v02i060: duonly - Program to display du output ONLY for a directory
  4. Message-ID: <7429@ncoast.UUCP>
  5. Date: 22 Feb 88 02:34:37 GMT
  6. Approved: allbery@ncoast.UUCP
  7.  
  8. Comp.sources.misc: Volume 2, Issue 60
  9. Submitted-By: "Dennis.Bednar" <dennis@rlgvax.UUCP>
  10. Archive-Name: duonly
  11.  
  12. SHORT blurb from the duonly.help file, just to summarize what
  13. this is program is for:
  14.  
  15. Prints disk usage block sizes only for directories,
  16. but NOT including sizes contributed by sub-directories.
  17.  
  18. This tool was developed because when viewing the output of a
  19. regular du, it was difficult to see which directories were
  20. the real culprits for occupying the most number of disk blocks.
  21.  
  22. #--------------- CUT HERE ---------------
  23. #! /bin/sh
  24. # This is a shell archive, meaning:
  25. # 1. Remove everything above the #! /bin/sh line.
  26. # 2. Save the resulting text in a file.
  27. # 3. Execute the file with /bin/sh (not csh) to create the files:
  28. #    duonly.c
  29. #    duonly.help
  30. # This archive created: Wed Feb 17 20:31:04 EST 1988
  31. #
  32. if test -f duonly.c
  33. then
  34. echo shar: will not over-write existing file 'duonly.c'
  35. else
  36. echo x - duonly.c
  37. # ............    F  I   L   E      B  E  G  .......... duonly.c
  38. cat << '\SHAR_EOF' > duonly.c
  39. /*
  40.  * duonly.c
  41.  * dennis bednar Feb 17, 1988
  42.  *
  43.  * Reads stdin of du output, and outputs sizes based ONLY on the
  44.  * space used within a directory only.  The size will be the
  45.  * number of blocks used by the directory itself, plus any
  46.  * files contained within that directory.
  47.  *
  48.  * NOTE:
  49.  * Much of the source code in dugraph.c (contributed to comp.unix.misc)
  50.  * I borrowed "as is".  What functions I added are at the end.
  51.  * I also added the "father" link.  All of the brothers of the
  52.  * first son, including the first son, have the same father node.
  53.  * That is, if we have /a/b, and /a/c, then "b" and "c" are brothers,
  54.  * and "b"'s and "c"'s father are both "a".  I also added a new
  55.  * variable "me_size" which is the size of the directory, not including
  56.  * the sizes of the sons immediately below it.
  57.  *
  58.  * NOTE: If you do "du /dir1/dir2/dir3| duonly", then the size of
  59.  * /dir1, and /dir2 will be 0, since they were NOT included in
  60.  * the original output of du!!!
  61.  *
  62.  * NOTE: if you do "du /dir1/dir2/dir3| duonly", then the root
  63.  * placeholder points to a cell for "", and NOT to "dir1" as
  64.  * you might expect.  This is because of how read_input() parses
  65.  * its input.  It is not a problem per se, except that the node
  66.  * containing a blank name should not be printed in this case.
  67.  * So, the solution is to add an extra check and avoid the print
  68.  * when the name is "".  By the way the root for "" only occurs
  69.  * because the pathnames are absolute (begin with a /).
  70.  *
  71.  * NOTE: although output of directory names are sorted there is
  72.  * one minor anomoly that occurs when you have input as follows
  73.  * (sizes ommited, since irrelevant):
  74.  * ../dir
  75.  * ...dir/RCS
  76.  * ...dir.ext
  77.  * The important point is that we have both a "/" and a "." after the
  78.  * same name "dir".
  79.  * A sort would place the "." before the "/" (ie line 3 before line 2),
  80.  * but the sort performed by du is only within each directory level, so
  81.  * that duonly would output line 2 before line 3 (since ../dir and
  82.  * ../dir.ext are sorted brothers, and ../dir/RCS is a sorted son of
  83.  * ../dir) !!
  84.  *
  85.  */
  86. #if 0
  87. Path: rlgvax!sundc!seismo!uunet!husc6!think!ames!necntc!ncoast!allbery
  88. From: drw@culdev1.UUCP (Dale Worley)
  89. Newsgroups: comp.sources.misc
  90. Subject: Prettyprint a du listing
  91. Message-ID: <6803@ncoast.UUCP>
  92. Date: 17 Dec 87 02:33:54 GMT
  93. Sender: allbery@ncoast.UUCP
  94. Organization: Cullinet Software, Westwood, MA, USA
  95. Lines: 447
  96. Approved: allbery@ncoast.UUCP
  97. X-Archive: comp.sources.misc/8712/8
  98.  
  99. I've always wanted to get a du listing that shows how the space is
  100. being used graphically.  I finally wrote a program to digest a du
  101. listing and print out a tree, where each directory occupies lines
  102. proportionally to how much space the files in it consume.
  103.  
  104. To run it, type "du | dugraph" or some such.  The listing for each
  105. directory starts with a blank space showing space occupied by files
  106. directly in that directory, then the subtrees for each subdirectory
  107. (in descending order of size).  If the subdirectories at the bottom
  108. get so small that they occupy less than 1 line each, they are all
  109. merged into an entry "(etc.)".
  110.  
  111. The entire listing always occupies 60 lines (the value of 'length').
  112. This program has tab-width = 5.
  113. --------------------------dugraph.c---------------------------------
  114. #endif
  115. /* program to make a pretty graph out of a du report */
  116.  
  117. #include <stdio.h>
  118. #include <string.h>
  119.  
  120. /* number of lines the listing should occupy */
  121. int    length = 60;
  122. /* message for suppressed directories */
  123. #define    SUPPRESSED    "(etc.)"
  124.  
  125. /* format of a tree node */
  126. struct node {
  127.             struct node    *lson;    /* left son */
  128.             struct node    *rbrother;/* right brother */
  129.             struct node    *father; /* parent node, up ptr */
  130.             unsigned long    size;    /* size of directory in kbytes */
  131.             unsigned long    me_size;    /* size of directory only */
  132.             int            loc;        /* location we will print it at */
  133.             int            print_col;/* column to print name in */
  134.             int            print_limit;
  135.                                 /* location we can't print on or
  136.                                  * after */
  137.             int            last;    /* are we last son of our father? */
  138.             char            name[1];    /* name */
  139.           };
  140.  
  141. /* root of the tree */
  142. struct node    *root = NULL;
  143. /* total size of things listed */
  144. unsigned long    total_size;
  145. /* current line number we are on (0-origin) */
  146. int            current_line = 0;
  147. /* list of where to put bars */
  148. int            bar_list[50];
  149. /* number of bars in the list */
  150. int            bar_count = 0;
  151.  
  152. /* declare functions */
  153. void            read_input();
  154. struct node    *insert_in_tree();
  155. void            dfs();
  156. void            dfs1();
  157. void            missing_sizes();
  158. void            sort_size();    /* sort tree by size */
  159. void            sort_name();    /* sort tree alphabetically */
  160. void            calc_loc();
  161. void            blank();
  162. void            mark_last();
  163. void            calc_pc();
  164. void            output();
  165. void            position();
  166. void            show_node();
  167. void            my_space();
  168.  
  169. main()
  170.     {
  171.     struct node    *t;    /* scratch */
  172.  
  173.     /* read the input and form a tree */
  174.     read_input();
  175.     root->size = 0;
  176.     /* put sizes on entries that have none */
  177.     dfs(NULL, missing_sizes);
  178.     /* sort each directory */
  179.     dfs(sort_name, NULL);
  180.  
  181.     /* for each directory, subtract the space used up by
  182.      * all children one level below me, so that we
  183.      * can tell how much space is occupied by this
  184.      * directory only.
  185.      * IMPORTANT: We need to compute in pre-order, or we
  186.      * won't get the right results.
  187.      */
  188.     dfs(my_space, NULL);
  189.  
  190.     /* print the tree */
  191.     dfs(show_node, NULL);
  192.     exit(0);
  193.  
  194.     /* unused left-over code I might need later. */
  195.  
  196.     /* calculate the total size */
  197.     total_size = 0;
  198.     for (t = root->lson; t != NULL; t = t->rbrother)
  199.         total_size += t->size;
  200.     /* calculate the location of each directory */
  201.     /* blank out subdirectories that get scrunched together at the bottom */
  202.     root->print_limit = length;
  203.     dfs(calc_loc, blank);
  204.     /* print out the tree */
  205.     for (t = root->lson; t != NULL; t = t->rbrother)
  206.         {
  207.         /* mark the last son of each directory */
  208.         /* figure out the print columns */
  209.         t->print_col = 0;
  210.         dfs1(calc_pc, mark_last, t);
  211.         dfs1(output, NULL, t);
  212.         }
  213.     /* put blank space at end */
  214.     position(length);
  215.     }
  216.  
  217. /* read input and form a tree */
  218. void read_input()
  219.     {
  220.     unsigned long    size;        /* size read from input */
  221.     char            name[100];    /* directory name read from input */
  222.  
  223.     /* make the dummy node at the top of the tree */
  224.     root = (struct node *)malloc(sizeof (struct node));
  225.     root->name[0] = '\0';
  226.     root->lson = NULL;
  227.     root->father = NULL;    /* if walking up the ladder, don't fall off ! */
  228.     /* read the next line of input */
  229.     while (fscanf(stdin, "%lu %s\n", &size, name) != EOF)
  230.         {
  231.         /* insert (or find) the directory in the tree and save its size */
  232.         insert_in_tree(name)->size = size;
  233.         }
  234.     }
  235.  
  236. /* insert (or find) a directory in the tree */
  237. struct node *insert_in_tree(name)
  238.     char    *name;        /* name of the directory */
  239.     {
  240.     struct node    *t;    /* pointer for searching down through tree */
  241.     char            *np;    /* points to next part of directory name to be
  242.                      * examined */
  243.     struct node    *t1;    /* scratch pointer */
  244.     char            *np1;/* scratch pointer */
  245.  
  246.     /* read through the name, one directory-part at a time, and hunt
  247.      * down the tree, constructing nodes as needed */
  248.     for (t = root, np = name; np != NULL; np = np1)
  249.         {
  250.         /* extract the next directory-part */
  251.         if ((np1 = strchr(np, '/')) != NULL)
  252.             {
  253.             /* we found a slash, replace it with a null, and position
  254.              * np1 to point to the remainder of the name */
  255.             /* can store node.name=="" when name begins with / */
  256.             *np1++ = '\0';
  257.             }
  258.         /* else */
  259.             /* we found no shash, so we are at the end of the name
  260.              * np1 has been set to NULL for us by strchr */
  261.         /* search the sons of this node for a node with the proper name */
  262.         for (t1 = t->lson; t1 != NULL && strcmp(t1->name, np) != 0;
  263.                 t1 = t1->rbrother)
  264.             ;
  265.         /* did we find one? */
  266.         if (t1 != NULL)
  267.             /* yes, go to it */
  268.             t = t1;
  269.         else
  270.             {
  271.             /* no, make one */
  272.             t1 = (struct node *)malloc(sizeof(struct node) + strlen(np));
  273.             strcpy(t1->name, np);
  274.             t1->lson = NULL;
  275.             t1->rbrother = NULL;
  276.             t1->father = t;
  277.             t1->size = 0;
  278.             /* insert it in tree */
  279.             t1->rbrother = t->lson;
  280.             t->lson = t1;
  281.             t = t1;
  282.             }
  283.         }
  284.     return t;
  285.     }
  286.  
  287. /* depth-first-search routine */
  288. void dfs(pre_routine, post_routine)
  289.     void    (*pre_routine)();    /* routine to execute before scanning
  290.                          * descendants */
  291.     void    (*post_routine)();    /* routine to execute after scanning
  292.                          * descendants */
  293.     {
  294.     dfs1(pre_routine, post_routine, root);
  295.     }
  296.  
  297. /* depth-first-search service routine */
  298. void dfs1(pre_routine, post_routine, t)
  299.     void    (*pre_routine)();    /* routine to execute before scanning
  300.                          * descendants */
  301.     void    (*post_routine)();    /* routine to execute after scanning
  302.                          * descendants */
  303.     struct node *t;        /* node to operate on */
  304.     {
  305.     struct node *t1;        /* scratch pointer */
  306.  
  307.     /* if it exists, execute the pre-routine */
  308.     if (pre_routine != NULL)
  309.         pre_routine(t);
  310.     /* call self on sons of this node */
  311.     for (t1 = t->lson; t1 != NULL; t1 = t1->rbrother)
  312.         dfs1(pre_routine, post_routine, t1);
  313.     /* if it exists, execute the post-routine */
  314.     if (post_routine != NULL)
  315.         post_routine(t);
  316.     }
  317.  
  318. /* add missing sizes */
  319. void missing_sizes(t)
  320.     struct node    *t;
  321.     {
  322.     struct node    *t1;        /* scratch pointer */
  323.     unsigned long    s;        /* scratch */
  324.  
  325.     if (t->size == 0)
  326.         {
  327.         /* size is missing, we have to calcuate it */
  328.         s = 0;
  329.         for (t1 = t->lson; t1 != NULL; t1 = t1->rbrother)
  330.             s += t1->size;
  331.         t->size = s;
  332.         }
  333.     }
  334.  
  335. /* sort the directories under a directory by size */
  336. void sort_size(t)
  337.     struct node    *t;
  338.     {
  339.     struct node    *p1, *p2, *p3, *pp;        /* scratch pointers */
  340.     int            nodes, n;                /* scratch */
  341.  
  342.     /* count the number of nodes */
  343.     nodes = 0;
  344.     for (p1 = t->lson; p1 != NULL; p1 = p1->rbrother)
  345.         nodes++;
  346.     /* just a simple and inefficient bubble sort */
  347.     for (n = 1; n < nodes; n++)
  348.         for (p1 = NULL, p2 = t->lson, p3 = p2->rbrother; p3 != NULL;
  349.                 p1 = p2, p2 = p3, p3 = p3->rbrother)
  350.             {
  351.             if (p2->size < p3->size)
  352.                 {
  353.                 /* exchange the nodes p2 and p3 */
  354.                 pp = p3->rbrother;
  355.                 p3->rbrother = p2;
  356.                 p2->rbrother = pp;
  357.                 if (p1 != NULL)
  358.                     p1->rbrother = p3;
  359.                 else
  360.                     t->lson = p3;
  361.                 /* exchange the values of p2 and p3 */
  362.                 pp = p2;
  363.                 p2 = p3;
  364.                 p3 = pp;
  365.                 }
  366.             }
  367.     }
  368.  
  369. /* calculate the print location */
  370. void calc_loc(t)
  371.     struct node    *t;
  372.     {
  373.     unsigned long    cs;        /* scratch */
  374.     struct node    *t1, *t2;    /* scratch pointers */
  375.     int            print_limit;
  376.                         /* location next directory after t will
  377.                          * be printed */
  378.  
  379.     if (t == root)
  380.         cs = 0;
  381.     else
  382.         {
  383.         /* figure out how much is in the directory itself */
  384.         for (t1 = t->lson, cs = 0; t1 != NULL; t1 = t1->rbrother)
  385.             {
  386.             cs += t1->size;
  387.             }
  388.         /* cs is the size accounted for by subdirectories */
  389.         cs = t->size - cs;
  390.         }
  391.     /* cs is the size of the files in the directory itself */
  392.     /* convert cs to lines */
  393.     cs = cs*length/total_size + t->loc;
  394.     /* calculate where next directory after t will be */
  395.     print_limit = t->print_limit;
  396.     /* assign locations */
  397.     for (t1 = t->lson, t2 = NULL; t1 != NULL; t2 = t1, t1 = t1->rbrother)
  398.         {
  399.         /* make sure we don't run into next directory */
  400.         if (cs >= print_limit)
  401.             {
  402.             cs = print_limit-1;
  403.             }
  404.         t1->loc = cs;
  405.         if (t2 != NULL)
  406.             t2->print_limit = cs;
  407.         cs += t1->size*length/total_size;
  408.         }
  409.     if (t2 != NULL)
  410.         t2->print_limit = print_limit;
  411.     }
  412.  
  413. /* figure out which directories to blank out */
  414. void blank(t)
  415.     struct node    *t;
  416.     {
  417.     struct node    *t1, *t2, *t3;        /* loop pointers */
  418.  
  419.     /* return if there aren't at least two sons */
  420.     if (t->lson == NULL || t->lson->rbrother == NULL)
  421.         return;
  422.     for (t1 = NULL, t2 = t->lson, t3 = t2->rbrother; t3 != NULL;
  423.             t1 = t2, t2 = t3, t3 = t3->rbrother)
  424.         if (t2->loc == t3->loc)
  425.             {
  426.             /* replace t1 and succeeding nodes with "(etc.)" */
  427.             t3 = (struct node *)malloc(sizeof (struct node) +
  428.                 sizeof (SUPPRESSED) - 1);
  429.             strcpy(t3->name, SUPPRESSED);
  430.             t3->lson = t3->rbrother = NULL;
  431.             t3->loc = t2->loc;
  432.             if (t1 == NULL)
  433.                 t->lson = t3;
  434.             else
  435.                 t1->rbrother = t3;
  436.             }
  437.     }
  438.  
  439. /* mark the last son of each directory */
  440. void mark_last(t)
  441.     struct node    *t;
  442.     {
  443.     struct node    *t1, *t2;    /* scratch pointers */
  444.     t->last = 0;
  445.     for (t1 = t->lson, t2 = NULL; t1 != NULL; t2 = t1, t1 = t1->rbrother)
  446.         ;
  447.     if (t2 != NULL)
  448.         t2->last = 1;
  449.     }
  450.  
  451. /* calculate the print columns */
  452. void calc_pc(t)
  453.     struct node    *t;
  454.     {
  455.     struct node    *t1;        /* scratch pointer */
  456.     int            c;        /* column suns will be printed in */
  457.  
  458.     c = t->print_col + strlen(t->name) + 5;
  459.     for (t1 = t->lson; t1 != NULL; t1 = t1->rbrother)    
  460.         t1->print_col = c;
  461.     }
  462.  
  463. /* write the output */
  464. void output(t)
  465.     struct node    *t;
  466.     {
  467.     position(t->loc);
  468.     printf("--%s%s", t->name, (t->lson != NULL ? "--+" : ""));
  469.     /* remove the bar for our father if we are the last son */
  470.     if (t->last)
  471.         bar_count--;
  472.     /* add the location of the bar to the bar list if we have a son */
  473.     if (t->lson != NULL)
  474.         {
  475.         bar_list[bar_count] = t->print_col + strlen(t->name) + 5 - 1;
  476.         bar_count++;
  477.         }
  478.     }
  479.  
  480. /* position to a specific line */
  481. void position(line)
  482.     int    line;        /* line number */
  483.     {
  484.     int    i;            /* counts through the bar list */
  485.     int    j;            /* current column number */
  486.  
  487.     /* for every line we need to go down */
  488.     for (; current_line < line; current_line++)
  489.         {
  490.         putchar('\n');
  491.         /* print the bars for this line */
  492.         j = 0;
  493.         for (i = 0; i < bar_count; i++)
  494.             {
  495.             for (; j < bar_list[i]; j++)
  496.                 putchar(' ');
  497.             if (current_line == line-1 && i == bar_count-1)
  498.                 putchar('+');
  499.             else
  500.                 putchar('|');
  501.             j++;
  502.             }
  503.         }
  504.     }
  505. #if 0
  506. -----------------------------------example-----------------------------------
  507. --.--+
  508.      |
  509.      |
  510.      |
  511.      |
  512.      |
  513.      |
  514.      |
  515.      +--scpp--+--ftps--+
  516.      |        |        +--scpp--+--temp
  517.      |        +--error
  518.      |        |
  519.      |        +--shar--+
  520.      |                 |
  521.      |                 +--temp
  522.      +--uemacs--+--uemacs3.9
  523.      |
  524.      |
  525.      |
  526.      |
  527.      |
  528.      |
  529.      +--patch--+--dist
  530.      |         |
  531.      |         |
  532.      |         +--build
  533.      |
  534.      |
  535.      |
  536.      +--sccs--+--all
  537.      |        |
  538.      |        |
  539.      |        |
  540.      |        +--(etc.)
  541.      +--yacctest
  542.      |
  543.      |
  544.      |
  545.      +--yacc
  546.      |
  547.      |
  548.      |
  549.      +--rnsend--+--dist1
  550.      |          +--dist3
  551.      |          +--dist2
  552.      +--bin--+
  553.      |       +--source
  554.      +--sources
  555.      |
  556.      +--kwfrob
  557.      +--rsts.tape
  558.      +--rnews
  559.      +--ftp-server
  560.      +--(etc.)
  561.  
  562.  
  563.  
  564.  
  565.  
  566.  
  567. ------------------------------end of example------------------------------
  568. -- 
  569. Dale Worley    Cullinet Software      ARPA: culdev1!drw@eddie.mit.edu
  570. UUCP: ...!seismo!harvard!mit-eddie!culdev1!drw
  571. Nothing shocks me -- I'm a scientist.
  572. #endif
  573.  
  574.  
  575. /* begin of new code added by dennis bednar */
  576. /*
  577.  * Print the full name associated with the path to this component.
  578.  * Since each node contains only one component of the full path name,
  579.  * in order to print out the entire name, we have to print the
  580.  * "father part of the component", followed by the component.
  581.  * This is why I invented the "father" up pointer.
  582.  * This is done recursively, I might add.
  583.  *
  584.  * the root is a dummy holder, it contains no real name.
  585.  * The top node which contains the first real name will have
  586.  * a father pointer to root.
  587.  * Rather, root -> lson contains the first real root of the tree.
  588.  * This is why root->rbrother is NULL.
  589.  *
  590.  * So do NOT print the root node's name.
  591.  * Also, when printing root->lson's father, it will be "".
  592.  */
  593. void
  594. show_node( p )
  595.     struct    node    *p;
  596. {
  597.     if (p == root)    /* just a placeholder, its lson is the real root */
  598.         return;    /* don't print jibberish */
  599.  
  600.     /* avoid printing root's lson node whose name is "".
  601.      * This occurs when first line of stdin contains a
  602.      * directory name beginning with a leading /.
  603.      * PS, since root node's name is also "", I probably could remove
  604.      * the "if" check above, and let this if stmt do the work of
  605.      * both, but I didn't feel like it.
  606.      */
  607.     if (p -> name[0] == '\0')
  608.         return;
  609.  
  610.     /* avoid printing /a and /b whose size is zero, just
  611.      * because we did a "du /a/b/c | duonly".
  612.      */
  613.     if (p -> me_size == 0L)
  614.         return;
  615.  
  616. /*    printf("'%s' and my father is <%s>\n", p -> name, p -> father -> name); */
  617.     printf("%ld\t", p -> me_size);
  618.     path_print(p);
  619.     putchar( '\n' );    /* terminate line */
  620. }
  621.  
  622. /*
  623.  * recursively print the full path by printing the "part before me",
  624.  * then printing my component name.
  625.  */
  626. path_print( p )
  627.     struct    node    *p;
  628. {
  629.     /* this should not ever happen, because of how path_print() is written */
  630.     if (p == NULL)
  631.         return;        /* paranenoid */
  632.  
  633.     /* this code is structured so that a leading slash will NOT
  634.      * be printed before the first component, but rather ONLY
  635.      * between all components, and NOT after the last component.
  636.      */
  637.     if (p -> father == root)
  638.         {
  639.         printf("%s", p ->name );
  640.         return;
  641.         }
  642.     else
  643.         {
  644.         /* recursion */
  645.         path_print( p -> father );    /* print components before me */
  646.         printf( "/%s", p -> name );    /* print my component */
  647.         }
  648. }
  649.  
  650. /*
  651.  * compute size of this directory only, ie don't include
  652.  * size of children directories.  This leaves space only
  653.  * occupied by this directory remaining in the "me_size".
  654.  */
  655. void
  656. my_space( p )
  657.     struct    node    *p;
  658. {
  659.     long    total = 0;
  660.     struct    node    *s;    /* each son of the parent p */
  661.  
  662.     total = p -> size;    /* blocks used by this directory */
  663.  
  664.     /* subtract blocks used by immediate children directories.
  665.      * WILL NOT WORK CORRECTLY if a child is a file !!!!!
  666.      * this will leave total containing only the number of blocks
  667.      * in this directory.
  668.      */
  669.     for ( s = p -> lson; s; s = s -> rbrother)
  670.         total -= s -> size;
  671.  
  672.     /* store my size only for this parent */
  673.     p -> me_size = total;
  674. }
  675.  
  676. /*
  677.  * sort the directories under a directory by name.
  678.  *
  679.  * this is just the old "sort()" routine [sort() renamed to
  680.  * sort_size() for clarity] with a minor change, where
  681.  * we now compare names, not size.  That is, we sort
  682.  * the brothers or peers at each level.
  683.  * SEE ALSO the anomoly concerning "." and "/" with regards
  684.  * to sorting, described at the top of this file.
  685.  */
  686. void sort_name(t)
  687.     struct node    *t;
  688.     {
  689.     struct node    *p1, *p2, *p3, *pp;        /* scratch pointers */
  690.     int            nodes, n;                /* scratch */
  691.     int    cmp;
  692.  
  693.     /* count the number of nodes */
  694.     nodes = 0;
  695.     for (p1 = t->lson; p1 != NULL; p1 = p1->rbrother)
  696.         nodes++;
  697.     /* just a simple and inefficient bubble sort */
  698.     for (n = 1; n < nodes; n++)
  699.         for (p1 = NULL, p2 = t->lson, p3 = p2->rbrother; p3 != NULL;
  700.                 p1 = p2, p2 = p3, p3 = p3->rbrother)
  701.             {
  702.             cmp = strcmp( p2 -> name, p3 -> name );
  703.             if (cmp > 0)    /* not alphabetized, p3 1st, p2 2nd */
  704.                 {
  705.                 /* exchange the nodes p2 and p3 */
  706.                 pp = p3->rbrother;
  707.                 p3->rbrother = p2;
  708.                 p2->rbrother = pp;
  709.                 if (p1 != NULL)
  710.                     p1->rbrother = p3;
  711.                 else
  712.                     t->lson = p3;
  713.                 /* exchange the values of p2 and p3 */
  714.                 pp = p2;
  715.                 p2 = p3;
  716.                 p3 = pp;
  717.                 }
  718.             }
  719.     }
  720.  
  721. \SHAR_EOF
  722. # ............    F  I   L   E      E  N  D  .......... duonly.c
  723. fi # end of overwriting check
  724. if test -f duonly.help
  725. then
  726. echo shar: will not over-write existing file 'duonly.help'
  727. else
  728. echo x - duonly.help
  729. # ............    F  I   L   E      B  E  G  .......... duonly.help
  730. cat << '\SHAR_EOF' > duonly.help
  731. duonly
  732.  
  733. Prints disk usage block sizes only for directories,
  734. but NOT including sizes contributed by sub-directories.
  735.  
  736. This tool was developed because when viewing the output of a
  737. regular du, it was difficult to see which directories were
  738. the real culprits for occupying the most number of disk blocks.
  739. For example, if you did a "du /usr", the last line would be
  740. something like:
  741.  
  742. 18112    /usr
  743.  
  744. even though /usr might only contain sub-directories, but no files.
  745. Hence, it might be that a sub-directory of /usr was the real
  746. culprit for being a disk hog, and not /usr (or a sub-sub-directory,
  747. etc., of /usr might be the culprit).
  748.  
  749. Duonly is designed to read standard input generated by "du", and print
  750. information in the same style as du:
  751.  
  752. size    directory_name
  753.  
  754. However, the size reported by duonly is the size in blocks
  755. contributed "ONLY by the directory_name itself, including
  756. the sum of the sizes of all regular files directly beneath
  757. directory_name".  It does NOT include the sizes inherited
  758. by ANY of the children directories.  Thus the size reported
  759. by duonly might be thought of as ONLY for that directory.
  760.  
  761.  
  762. SAMPLE USAGE
  763.  
  764.     du | duonly
  765.     du /usr | duonly
  766.  
  767.  
  768. NOTES
  769.  
  770. The directory names are sorted alphabetically by each level.
  771. There is one minor anomoly about the sorted order of directory
  772. names. Duonly will output this order:
  773.     10    dir
  774.     5    dir/subdir
  775.     3    dir.2
  776. but a true "du | duonly | sort +1", with sorting applied to
  777. the second column would really output:
  778.     10    dir
  779.     3    dir.2
  780.     5    dir/subdir
  781. since "." lexically preceeds "/".
  782. With the exception noted, the rest of the output generated by du
  783. is in the correct order.
  784. \SHAR_EOF
  785. # ............    F  I   L   E      E  N  D  .......... duonly.help
  786. fi # end of overwriting check
  787. # end of shell archive
  788. exit 0
  789. -- 
  790. FullName:    Dennis Bednar
  791. UUCP:        {uunet|sundc}!rlgvax!dennis
  792. USMail:        CCI; 11490 Commerce Park Dr.; Reston VA 22091
  793. Telephone:    +1 703 648 3300
  794.